package com.starlinkdt.common.storage;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.poi.util.IOUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;

/**
 * 对象存储
 *
 * @author system
 */
@Configuration
public class StorageUtils {
    private final String DOT = ".";
    private final StorageInterface storageInterface;

    public StorageUtils() {
        this.storageInterface = StorageFactory.generate(StorageEnum.Minio);
    }

    public StorageUtils(StorageEnum storageEnum) {
        this.storageInterface = StorageFactory.generate(storageEnum);
    }

    /**
     * 获取扩展名
     * @return String
     */
    private String genExtName(String fileStr) {
        String MARK = "?";
        String filePath = fileStr.indexOf(MARK) > 0 ? fileStr.substring(0, fileStr.indexOf(MARK)) : fileStr;
        return filePath.lastIndexOf(this.DOT) > 0 ? filePath.substring(filePath.lastIndexOf(this.DOT) + 1) : "";
    }

    /**
     * 获取存储文件名
     *
     * @param dirPath 存储目录地址
     * @param objectContent 存储对象内容
     * @param extName 存储扩展名
     * @return String
     */
    private String genByteObjectName(String dirPath, byte[] objectContent, String extName) {
        String DIV = "/";
        return (dirPath.isEmpty() ? "" : dirPath ) + DIV +
                (extName.isEmpty()? "" : extName + DIV) +
                DigestUtils.md5Hex(objectContent) + this.DOT + extName;
    }

    /**
     * 保存存储文件
     *
     * @param dirPath 存储目录地址
     * @param objectContent 存储对象内容
     * @param extName 存储扩展名
     * @return String
     */
    public String putByteObject(String dirPath, byte[] objectContent, String extName) throws Exception {
        String objectName = genByteObjectName(dirPath, objectContent, extName);
        this.storageInterface.putObjectByte(objectName, objectContent);
        return objectName;
    }

    /**
     * 保存存储文件
     *
     * @param dirPath 存储目录地址
     * @param fileName 对象路径及名称
     * @return String
     */
    public String putFileObject(String dirPath, String fileName) throws Exception {
        return putFileObject(dirPath, fileName, genExtName(fileName));
    }

    /**
     * 保存存储文件
     *
     * @param dirPath 存储目录地址
     * @param fileName 对象路径及名称
     * @param extName 存储扩展名
     * @return String
     */
    public String putFileObject(String dirPath, String fileName, String extName) throws Exception {
        try (InputStream inputStream = Files.newInputStream(Paths.get(fileName))) {
            byte[] objectContent = IOUtils.toByteArray(inputStream);
            return putByteObject(dirPath, objectContent, extName);
        }
    }

    /**
     * 保存存储文件
     *
     * @param dirPath 存储目录地址
     * @param fileUrl 对象路径及名称
     * @return String
     */
    public String putUrlObject(String dirPath, String fileUrl) throws Exception {
        return putUrlObject(dirPath, fileUrl, genExtName(fileUrl));
    }

    /**
     * 保存存储文件
     *
     * @param dirPath 存储目录地址
     * @param fileUrl 对象路径及名称
     * @param extName 存储扩展名
     * @return String
     */
    public String putUrlObject(String dirPath, String fileUrl, String extName) throws Exception {
        try (InputStream inputStream = new URL(fileUrl).openStream()) {
            byte[] objectContent = IOUtils.toByteArray(inputStream);
            return putByteObject(dirPath, objectContent, extName);
        }
    }

    /**
     * 获取签名URL
     *
     * @param objectName 对象路径及名称
     * @return String
     */
    public String getObjectSignUrl(String objectName) {
        return this.storageInterface.getObjectSignUrl(objectName);
    }

    public String putMultipartFile(MultipartFile file, String path) throws Exception {
        // 保存文件
        String extName = Objects.requireNonNull(file.getOriginalFilename())
                .substring(file.getOriginalFilename().lastIndexOf(".") + 1);

        return putByteObject(path, file.getBytes(), extName);
    }

}
